import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import logger from 'src/common/utils/log';
import { MatchInfo } from 'src/modules/match/entities/match.entity';
import { MatchStatusEnum } from 'src/common/constant/enums';
import { keyBy } from 'lodash';
import { MatchService } from 'src/modules/match/match.service';
import { UpdateMatchDto } from './dto/update-match.dto';
import { MatchGiveUpService } from '../match-end/match-giveup.service';
@Injectable()
export class MatchReadyService {
  constructor(
    private readonly matchGiveUpService: MatchGiveUpService,
    private readonly matchService: MatchService,
  ) {}

  async matchReadyHandler(matchInfos: MatchInfo[]) {
    matchInfos.forEach((match) => {
      match.status = MatchStatusEnum.Ready;
    });
    return this.matchService.saveList(matchInfos);
  }
  async hasByePlayerMatchHandler(matchInfos: MatchInfo[]) {
    const matchIds = matchInfos.map((match) => match.id);
    const handleByeMatches = [];
    matchInfos.forEach((match) => {
      if (!match.subMatchId || !matchIds.includes(match.subMatchId)) {
        // 这里需要考虑，团赛既有子比赛又有付父比赛，会导致子比赛重复修改
        handleByeMatches.push(match);
      }
    });
    const promiseList = handleByeMatches.map((match) => {
      return this.endMatch(match);
    });
    const res = await Promise.all(promiseList);
    return res;
  }

  async endMatch(matchInfo: MatchInfo) {
    logger.info(`start end match ${matchInfo.id} in match ready`);
    const loser = matchInfo.homePlayer.isByePlayer
      ? matchInfo.homePlayer
      : matchInfo.awayPlayer;
    // 证明这是团队赛的子比赛
    await this.matchGiveUpService.playerGiveUp(
      matchInfo.id.toString(),
      loser.id.toString(),
      'player',
      {
        operator: {
          id: matchInfo.createBy,
        } as any,
      },
    );
  }

  checkIsByePlayerMatch(matchInfo: MatchInfo) {
    if (
      matchInfo.homePlayer?.isByePlayer ||
      matchInfo.awayPlayer?.isByePlayer
    ) {
      return true;
    }
  }
  async matchReady(matchList: UpdateMatchDto[]) {
    if (!matchList || !matchList.length) {
      throw new HttpException(
        `入参为空,无法ready`,
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
    logger.info(`start matchReady params matchList ${matchList.length}`);
    const createBy = matchList[0].createBy;
    const updateBy = matchList[0].updateBy;
    const matchIds = matchList.map((match) => match.id);
    const matchInfos = await this.matchService.listByIds(matchIds);
    const inputMatchesKeyById = keyBy(matchList, 'id');
    if (!matchInfos || !matchInfos.length) {
      throw new HttpException(
        `比赛不存在,无法ready ${matchIds.join(',')}`,
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
    const hasByePlayerMatches: MatchInfo[] = [];
    const readyMatches: MatchInfo[] = [];
    for (const match of matchInfos) {
      // 将所有比赛的状态设置为 ready
      // match.status = MatchStatusEnum.Ready;
      // 将所有有轮空的比赛挑选出来
      const updateMatch = {
        ...match,
        ...inputMatchesKeyById[match.id],
        updateBy,
      };
      if (this.checkIsByePlayerMatch(match)) {
        logger.info(`match ${match.id} has bye player`);
        hasByePlayerMatches.push(updateMatch);
      } else {
        logger.info(`match ${match.id} will is ready`);
        readyMatches.push(updateMatch);
      }
    }
    // return this.matchService.saveList(matchList);
    // 这里需要考虑，团赛既有子比赛又有付父比赛，会导致子比赛重复修改
    if (readyMatches.length) {
      await this.matchReadyHandler(readyMatches);
    }
    if (hasByePlayerMatches.length) {
      await this.hasByePlayerMatchHandler(hasByePlayerMatches);
    }
  }
}
